﻿using System;
using System.Collections.Generic;

namespace Pixels.Logic
{

    public interface IAssignationTarget {

        void loseColonist(Colonist c);
        void gainColonist(Colonist c);

        int numColonists();
        IEnumerable<Colonist> ListColonists();
        Tile getTile();
    }

    public class Colonist : IComparable<Colonist>
    {

        private readonly Colony myColony;

        public Colonist(Colony colony, Occupation t) {

            uniqueID = _counter++;

            this.myColony = colony;
            this.MyOccupation = t;
            
            this.AssignedToTarget = null;            
            
        }

        //private Structure _struct;
        //public Structure AssignedToStructure {
        //    get {
        //        return _struct;
        //    }
        //    set {
        //        if (_struct != null) _struct.loseColonist(this);
        //        _struct = value;
        //        if (_struct != null) _struct.gainColonist(this);

        //        if (_struct == null) myColony.idleColonists.Add(this); else myColony.idleColonists.Remove(this);
        //    }
        //}

        private IAssignationTarget _workingAt;
        public IAssignationTarget AssignedToTarget {

            get {
                return _workingAt;
            }

            set {
                if (_workingAt != null) _workingAt.loseColonist(this);
                _workingAt = value;
                if (_workingAt != null) _workingAt.gainColonist(this);
                if (_workingAt == null) myColony.idleColonists.Add(this); else myColony.idleColonists.Remove(this);    
            }
        }


        public enum Occupation
        {
            colonist,
            technician,
            soldier
        }

        private Occupation myOccupation;
        public Occupation MyOccupation { 
            get { return myOccupation;  }
            set { myOccupation = value; }
        }

        public void die() {
            AssignedToTarget = null; // to idle pool
            myColony.removeColonist(this);
        }


        int IComparable<Colonist>.CompareTo(Colonist other) {
            return Ur.Maths.sgn(((int)myOccupation - (int)other.myOccupation) * 5000 + (uniqueID - other.uniqueID) ) ;

        }


        internal void executeTurn() {
            if (this.MyOccupation == Occupation.colonist) {
                if (this.AssignedToTarget != null) {
                    if (this.AssignedToTarget is Structures.Laboratory) {
                        this.AssignedToTarget = null;
                        this.MyOccupation = Occupation.technician;
                    }
                }
                if (this.AssignedToTarget != null) {
                    if (this.AssignedToTarget is Structures.Bunker) {
                        this.AssignedToTarget = null;
                        this.MyOccupation = Occupation.soldier;
                    }
                }
            }

        }

        public readonly int uniqueID;
        private static int _counter;

        public override bool Equals(object obj) {
            var o2 = obj as Colonist; if (o2 == null) return false;
            return o2.uniqueID == this.uniqueID;
        }

        public override int GetHashCode() { return uniqueID;}

        public bool Idle { get { return AssignedToTarget == null; } }

        internal bool canAssignTo(Tile atTile) {
            if (atTile.HasStructure && atTile.StructureOnTile.canAccomodateColonist(this)) return true;
            if (atTile.visibility == Visibility.discoverable && this.MyOccupation == Occupation.soldier && atTile.discoveryHandle.colonists.Count < 3) return true;

            return false;
        }

        internal void assignToTile(Tile atTile) {
            if (atTile.HasStructure && atTile.StructureOnTile.canAccomodateColonist(this)) this.AssignedToTarget = atTile.StructureOnTile;
            if (atTile.visibility == Visibility.discoverable && this.MyOccupation == Occupation.soldier && atTile.discoveryHandle.colonists.Count < 3) this.AssignedToTarget = atTile.discoveryHandle;
        }


        static public string[] icons_frontal = new[] { "colonist_front", "technician_front", "soldier_front" };
        static public string[] icons_iso     = new[] {"colonist_iso", "technician_iso", "soldier_iso" };

        public string getFrontalIcon(){  return icons_frontal[(int)this.MyOccupation]; }
        public string getIsometricIcon() { return icons_iso[(int)this.MyOccupation]; }
    }
}